const express = require('express');
const winston = require('winston');
const schedule = require('node-schedule');
const moment = require('moment');
const engines = require('consolidate');
const utils = require('./common/FooUtils.js');
const connection = require('./common/CommonMysqlServer.js');
const mysql = require('mysql');

const bodyParser = require('body-parser');
const multer = require('multer'); // v1.0.5
const upload = multer(); // for parsing multipart/form-data

const logger = initExpressLogger();
const app = express();

bind_common_http_server();
bind_reactNative_crud();
bind_alfredUrls_crud();
bind_exception();

function bind_exception(){
	app.use(function(req, res, next) {
		res.redirect('/open/404.html');
	});	
}

function bind_common_http_server() {
	
	// for parsing application/json
	app.use(bodyParser.json()); 
	// for parsing application/x-www-form-urlencoded
	app.use(bodyParser.urlencoded({ extended: true })); 
	
	
	app.locals.email = "nevermissing@vip.qq.com";
	// __dirname = '/Users/Steve/tools/myGit/xNode';
	logger.info("success initExpressGlobalConsts on:%s",__dirname);

	app.engine('html', engines.mustache);
	app.set('view engine', 'html');
	app.set('views', __dirname + '/views');
	logger.info("success initExpressHtmlEngine");

    const port = 8888;
    app.listen(port);
	logger.info("success bind httpServer on port:%s", port);

	// mount static files.
	app.use('/open', express.static(__dirname+'/public'));
	
	app.all('/', function(req, res) {
		res.type('.html');
		res.sendFile(__dirname+'/public/index.html');
	});

	app.get('/test', function(req, res) {
		res.render('one/test.html', {
			token : __dirname
		});
	});

	logger.info("success initHttpServer");
}

function bind_reactNative_crud() {

    const urlPrefix = '/reactNative/props';
    const crud_list_paging_url = urlPrefix + '/list';
    const crud_list_all_url = urlPrefix + '/listAll';
    const crud_saveOrUpdate_url = urlPrefix + '/saveOrUpdate';
    const crud_delete_url = urlPrefix + '/delete';
    const tablePrefix = 'react_native_props';

    app.all(crud_list_all_url, function(req, res) {
        const querySql = "select * from " + tablePrefix + " where 1=1 order by create_time desc";
        const resultObject = {recordsFiltered: 0, recordsTotal: 0, data: ''};

        const countChain = connection.executeSql(querySql).then(
            function (rows) {
                resultObject.recordsFiltered = resultObject.recordsTotal = rows.length;
                resultObject.data = rows;
                const result = JSON.stringify(resultObject);
                res.send(result);
            }).catch(function (err) {
            logger.error(err);
            res.send(err);
        });
    });
	
	app.post(crud_delete_url, upload.array(), function (req, res, next) {
        const params = [mysql.escape(req.body.myIds)];
        const sql = "delete from " + tablePrefix + " where id in (" + mysql.escape(req.body.myIds) + " ) ";
        connection.executeSql(sql,params).then(
				function(result) {
					logger.info("you have delete rows of:%s",result.affectedRows);
					res.send(JSON.stringify({ret:0}));
				}).catch(function(err){
					logger.error(err);
					res.send(JSON.stringify({ret:-1,msg:err}));
				});
	});
	
	app.post(crud_saveOrUpdate_url, upload.array(), function (req, res, next) {

        let type;
        const currentDate = moment().toDate();
        if(req.body){
			if(req.body.id){
				type = "update";
			}else{
				type = "save";
			}
		}else{
			res.send(JSON.stringify('{ret:-1}'));
			return;
		}
		logger.info('type is: %s',type);
		if(type == "save"){
			logger.info('saving here.');
			var model = {
					id: utils.generateUUID(),
					name: req.body.name,
					value: req.body.value,
					desc: req.body.desc,
					create_time:currentDate,
					last_check_time:currentDate
			};
			logger.info('saving model of:%s',model);
			var sql = "insert into "+tablePrefix+" set ? ";
            const successJson = {ret: 0};
            const failureJson = {ret: -1};
            connection.executeSql(sql, model).then(
					function(rows) {
						res.send(JSON.stringify(successJson));
					}).catch(function(err){
						logger.error(err);
						res.send(JSON.stringify(failureJson));
					});
			return;
		}else if(type=="update"){
			var model = {
					name: req.body.name,
					value: req.body.value,
					desc: req.body.desc,
					create_time:currentDate,
					last_check_time:currentDate
			};
            const params = [req.body.keyword, req.body.url, req.body.desc, req.body.id];
            var sql = "update "+tablePrefix+" set ? where id = "+mysql.escape(req.body.id)+ " ";
			connection.executeSql(sql, model).then(
					function(rows) {
						res.send(JSON.stringify({ret:0}));
					}).catch(function(err){
						logger.error(err);
						res.send(JSON.stringify({ret:-1}));
					});
			return;
		}else{
			res.send(JSON.stringify({ret:0}));
			return;
		}
	});
	
	app.post(crud_list_paging_url, function(req, res) {
        const params = [req.query.mobile];

        const length = parseInt(req.body.length);
        const start = parseInt(req.body.start);
        const pagingStr = start + ',' + length;

        const querySql = "select * from " + tablePrefix + " where 1=1 limit " + pagingStr;
        const countSql = "select count(*) as result from alfred_workflow_urls where 1=1";
        const resultObject = {recordsFiltered: 0, recordsTotal: 0, data: ''};

        const countChain = connection.executeSql(countSql, params).then(
            function (rows) {
                const totalLength = rows[0].result;
                resultObject.recordsFiltered = resultObject.recordsTotal = totalLength;
                return connection.executeSql(querySql, params);
            }).then(
            function (rows) {
                resultObject.data = rows;
                const result = JSON.stringify(resultObject);
                res.send(result);
            }).catch(function (err) {
            logger.error(err);
            res.send(err);
        });
    });
	
	
}

function initExpressLogger() {
    const logger = new (winston.Logger)(
        {
            transports: [new (winston.transports.Console)(
                {
                    timestamp: function () {
                        return moment().format();
                    },
                    formatter: function (options) {
                        // Return string will be passed to logger.
                        return options.timestamp()
                            + ' '
                            + options.level.toUpperCase()
                            + ' '
                            + (undefined !== options.message ? options.message
                                : '')
                            + (options.meta
                            && Object.keys(options.meta).length ? '\n\t'
                                + JSON.stringify(options.meta)
                                : '');
                    }
                })]
        });
    logger.info("success init global logger.");
	return logger;
}

function bind_alfredUrls_crud(){
	app.post('/alfred/workflow/listUrl', function(req, res) {
        const params = [req.query.mobile];

        const length = parseInt(req.body.length);
        const start = parseInt(req.body.start);
        const pagingStr = start + ',' + length;

        const querySql = "select * from alfred_workflow_urls where 1=1 limit " + pagingStr;
        const countSql = "select count(*) as result from alfred_workflow_urls where 1=1";
        const resultObject = {recordsFiltered: 0, recordsTotal: 0, data: ''};

        const countChain = connection.executeSql(countSql, params).then(
            function (rows) {
                const totalLength = rows[0].result;
                resultObject.recordsFiltered = resultObject.recordsTotal = totalLength;
                return connection.executeSql(querySql, params);
            }).then(
            function (rows) {
                resultObject.data = rows;
                const result = JSON.stringify(resultObject);
                res.send(result);
            }).catch(function (err) {
            logger.error(err);
            res.send(err);
        });
    });
	
	app.all('/alfred/workflow/listAllUrl', function(req, res) {
        const querySql = "select * from alfred_workflow_urls where 1=1 order by last_check_time desc";
        const resultObject = {recordsFiltered: 0, recordsTotal: 0, data: ''};

        const countChain = connection.executeSql(querySql).then(
            function (rows) {
                resultObject.recordsFiltered = resultObject.recordsTotal = rows.length;
                resultObject.data = rows;
                const result = JSON.stringify(resultObject);
                res.send(result);
            }).catch(function (err) {
            logger.error(err);
            res.send(err);
        });
    });
	
	app.post('/alfred/workflow/deleteUrl', upload.array(), function (req, res, next) {
        const params = [mysql.escape(req.body.myIds)];
        const sql = "delete from alfred_workflow_urls where id in (" + mysql.escape(req.body.myIds) + " ) ";
        connection.executeSql(sql,params).then(
				function(result) {
					logger.info("you have delete rows of:%s",result.affectedRows);
					res.send(JSON.stringify({ret:0}));
				}).catch(function(err){
					logger.error(err);
					res.send(JSON.stringify({ret:-1,msg:err}));
				});
	});
	
	app.post('/alfred/workflow/saveOrUpdateUrl', upload.array(), function (req, res, next) {

        let type;
        const currentDate = moment().toDate();
        if(req.body){
			if(req.body.id){
				type = "update";
			}else{
				type = "save";
			}
		}else{
			res.send(JSON.stringify(failureJson));
			return;
		}
		if(type == "save"){
			var model = {
					id: utils.generateUUID(),
					keyword: req.body.keyword,
					url: req.body.url,
					desc: req.body.desc,
					create_time:currentDate,
					last_check_time:currentDate
			};
			var sql = "insert into alfred_workflow_urls set ? ";
            const successJson = {ret: 0};
            var failureJson = {ret:-1};
			connection.executeSql(sql, model).then(
					function(rows) {
						res.send(JSON.stringify(successJson));
					}).catch(function(err){
						logger.error(err);
						res.send(JSON.stringify(failureJson));
					});
			return;
		}else if(type=="update"){
			var model = {
					keyword: req.body.keyword,
					url: req.body.url,
					desc: req.body.desc,
					create_time:currentDate
			};
            const params = [req.body.keyword, req.body.url, req.body.desc, req.body.id];
            var sql = "update alfred_workflow_urls set ? where id = "+mysql.escape(req.body.id)+ " ";
			connection.executeSql(sql, model).then(
					function(rows) {
						res.send(JSON.stringify({ret:0}));
					}).catch(function(err){
						logger.error(err);
						res.send(JSON.stringify({ret:-1}));
					});
			return;
		}else{
			res.send(JSON.stringify({ret:0}));
			return;
		}
	});
}
